<?php

class Pfinal_Remoting_Curl {
	
	/**
	 * 
	 * @var Pfinal_Remoting_Config
	 */
	protected $conf;
	
	/**
	 * 
	 * @var 
	 */
	protected $curl;
	
	public function __construct(Pfinal_Remoting_Config $conf){
		$this->conf = $conf;
	}
	
	protected function initCurlOption(){
		$this->curl = curl_init();
		curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true);
		curl_setopt($this->curl, CURLOPT_CONNECTTIMEOUT, $this->conf->getTimeout());
		curl_setopt($this->curl, CURLOPT_TIMEOUT, $this->conf->getTimeout());
		curl_setopt($this->curl, CURLOPT_AUTOREFERER, true);
	}
	
	public function get($service,$params){
		$retryTime = $this->conf->getRetryTimes();
		$servers = $this->conf->getServers();
		try{
			while ($retryTime--&&!empty($servers)){
				$server = array_pop($servers);
				$params = $this->signature($server, $params);
				$url = sprintf('%s/%s?%s,',$server->getHost(),$service,http_build_query($params));	
				$this->initCurlOption();				
				curl_setopt($this->curl, CURLOPT_URL, $url);	
				$ret = curl_exec($this->curl);
				if (curl_error($this->curl)){
					throw new Pfinal_Exception_Runtime(curl_error($this->curl), curl_errno($this->curl));
				}
				
				if (empty($ret)){
					throw new Pfinal_Exception_Runtime('malformed return from curl get:'.$url,-1);
				}
				
				return $ret;
			}
		}catch(Exception $ex){
			if (!$retryTime){
				throw new Pfinal_Exception_Runtime('curl get failure after max retry times:'.print_r($ex->getMessage()),$ex->getCode());
			}
		}
	}
	
	public function post($service,$params){
		$retryTime = $this->conf->getRetryTimes();
		$servers = $this->conf->getServers();
		try{
			while ($retryTime--&&!empty($servers)){
				$server = array_pop($servers);
				$params = $this->signature($server, $params);
				$url = sprintf('%s/%s,',$server->getHost(),$service);
				$this->initCurlOption();
				curl_setopt($this->curl, CURLOPT_URL, $url);
				curl_setopt($this->curl, CURLOPT_POST, true);
				curl_setopt($this->curl, CURLOPT_POSTFIELDS,$params);
				$ret = curl_exec($this->curl);
				if (curl_error($this->curl)){
					throw new Pfinal_Exception_Runtime(curl_error($this->curl), curl_errno($this->curl));
				}
		
				if (empty($ret)){
					throw new Pfinal_Exception_Runtime('malformed return from curl get:'.$url,-1);
				}
				return $ret;
			}
		}catch(Exception $ex){
			if (!$retryTime){
				throw new Pfinal_Exception_Runtime('curl get failure after max retry times:'.print_r($ex->getMessage()),$ex->getCode());
			}
		}
	}
	
	/**
	 * 
	 */
	public function __call($name,$argument){
		$service = $name;
		return call_user_func_array(array($this,'post'), array($service,$argument));
	}
	
	protected function signature(Pfinal_Remoting_Server $server,$params){
		$key = $server->getKey();
		$secret = $server->getSecret();
		if (empty($key) || empty($secret)){
			return $params;
		}else{
			unset($params['api_sign']);
			$params['api_key'] = $key;
			ksort($params);
			$content = '';
			foreach ($params as $param){
				if (is_array($param)){
					$content .= json_encode($param);
				}else{
					$content .= $param;
				}
			}
			$content .= $secret;
			$signature = md5($content);
			$params['api_sign'] = $signature;
			$params['api_key'] = $key;
		}
		return $params;
	}
	
	public function __destruct(){
		if (is_resource($this->curl)){
			curl_close($this->curl);
		}
	}
	
}